/**
 * Flash-based proxy for cross-domain requests
 * @author aflesler
 */

function Cajax() {
	this._init();
};

(function(){

	var uid = 0, queue,	instances, swf, noHeaders;
	
	// Cajax Class
	// The public API is based on http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060405/
	
	Cajax.prototype = {
		_init:function() {
			this._id = uid++;
			instances[this._id] = this;
		},
		open:function(method, url, async, user, pass) {
			this.readyState = 1;
			this._reqHeaders = {};
			this._method = method;
			this._url = url;
			// TODO: The rest?
		},
		/*onreadystatechange:function(){
			this.readyState === 4
		},*/
		send:function(data) {
			this._data = data;
			if (queue)
				queue.push(this);
			else
				this._send();
		},
		_send:function() {
			swf.request(this._id, this._url, this._method, this._data, this._reqHeaders);
		},		
		abort:function() {
			swf.abort(this._id);
			delete instances[this._id];
		},
		setRequestHeader:function(header, value){
			if (noHeaders && header.toLowerCase() !== 'content-type')
				return;

			var h = this._reqHeaders;
			if (h[header])
				h[header] += ', ' + value;
			else
				h[header] = value;
		},
		getAllResponseHeaders:function(){
			return '';
		},
		getResponseHeader:function(header){
			return null;
		},
		readyState:0,
		_handle:function(data){
			delete instances[this._id];
			
			this.readyState = 4;
			this.responseText = data;
			this.responseXML = decodeXML(data);
			this.status = 200;
			this.statusText = 'OK';
			if (this.onreadystatechange)
				this.onreadystatechange();
		}
	};
	
	// Utils
	
	function decodeXML(data) {
		if (!isXML(data))
			return null;
		
		var doc;
		if (this.DOMParser) {
			doc = new DOMParser().parseFromString(data, 'text/xml');
		} else {
			doc = new ActiveXObject('Microsoft.XMLDOM'); 
			doc.async = false;
			doc.loadXML(data);
		}
		return doc;
	};
	
	function isXML(data) {
		return typeof data === 'string' &&
			data.slice(0, 5) === '<?xml';
			// data.charAt(0) !== '<';
	};
	
	function createSwf(url, parent) {
		var div = document.createElement('div'),
			s = div.style,
			ieFix = this.ActiveXObject ? ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' : '';
			
		s.position = 'absolute'
		s.left = '-1px';
		div.innerHTML = '<object id="cajax" data="'+url+'" type="application/x-shockwave-flash"'+ieFix+' width="1" height="1">' +
							'<param name="allowScriptAccess" value="always" />' +
							'<param name="movie" value="'+url+'" />' +
						'</object>';
		parent.appendChild(div);
		return div.firstChild;
	};
	
	// SWF setup & destroy
	
	Cajax.init = function(url, parent, disableHeaders) {
		queue = [];
		instances = {};
		noHeaders = disableHeaders;
		swf = createSwf(url, parent);
	};
	
	Cajax.destroy = function() {
		var div = swf.parentNode;
		div.parentNode.removeChild(div);
		// TODO: Abort active requests?
		swf = queue = instances = null;		
	};
	
	// JS-AS Communication
	
	Cajax._success = function(id, data) {
		var cajax = instances[id];
		cajax._handle(unescape(data));
	};
	
	Cajax._error = function(msg) {
		alert('Cajax Error > ' + msg);
	};
	
	Cajax._dequeue = function() {
		while (queue.length) {
			queue.shift()._send();
		}
		queue = null;
	};

})();